package com.example.lock;

import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicStampedReference;

/**
 * @Author: sn
 * @Desc something
 * @Date: 2021/9/14
 */
public class ABATest {

    private static AtomicInteger atomicInteger = new AtomicInteger(1);
    private static AtomicStampedReference atomicStampedReference = new
            AtomicStampedReference(1, 1);
    public static void main(String[] args) throws InterruptedException {
        //ABA问题演示：
        // 1. atomicIntegerThread1先对数据进行修改 A-B-A过程
        // 2. atomicIntegerThread2也对数据进行修改 A-C的过程
        // atomicIntegerThread2修改 A-C 的时候，不知道A是原来的A还是atomicIntegerThread1先对数据进行修改之后的A
        Thread atomicIntegerThread1 = new Thread(() -> {
            atomicInteger.compareAndSet(1, 2);
            atomicInteger.compareAndSet(2, 1);
        });
        Thread atomicIntegerThread2 = new Thread(() -> {
            try {
    //睡一会，让atomicIntegerThread1先执行完
                TimeUnit.SECONDS.sleep(1);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println("AtomicInteger:" + atomicInteger.compareAndSet(1, 3));
            System.out.println("AtomicIntegerTest result：" + atomicInteger.get());
        });
        atomicIntegerThread1.start();
        atomicIntegerThread2.start();
    //顺序执行，让atomicIntegerThread先执行完成
        atomicIntegerThread1.join();
        atomicIntegerThread2.join();
    //AtomicStampedReference每次修改都需要设置标识Stamp，相当于进行了1A-2B- 3A的操作
        Thread atomicStampedReferenceThread1 = new Thread(() -> {
            try {
    //睡一会，让atomicStampedReferenceThread1先获取 旧的Stamp
                TimeUnit.SECONDS.sleep(1);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
    // 预期引用：1，更新后的引用：2，预期标识getStamp() 更新后的标识 getStamp() + 1
            atomicStampedReference.compareAndSet(1, 2, atomicStampedReference.getStamp(),
                    atomicStampedReference.getStamp() + 1);
            atomicStampedReference.compareAndSet(2, 1, atomicStampedReference.getStamp(),
                    atomicStampedReference.getStamp() + 1);
        });
    //atomicStampedReferenceThread2进行操作的时候，虽然数值都一样，但是可以根据标识很容易的知道A是以前的1A，还是现 在的3A
        Thread atomicStampedReferenceThread2 = new Thread(() -> {
    //atomicStampedReferenceThread2先获取stamp，发现预期stamp不一致
            int stamp = atomicStampedReference.getStamp();
            try {
    //睡一会，让atomicStampedReferenceThread1先执行完
                TimeUnit.SECONDS.sleep(2);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println("AtomicStampedReference:" +
                    atomicStampedReference.compareAndSet(1, 3, stamp, stamp + 1));
            int[] stampArr = {stamp + 1};
            System.out.println("AtomicStampedReferenceTest result：" +
                    atomicStampedReference.get(stampArr));
        });
        atomicStampedReferenceThread1.start();
        atomicStampedReferenceThread2.start();
    }
}